
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
/**
 * La classe Progetto estende la classe JFrame ereditandone tutte le proprietà.
 * Si occupa di gestire il frame del programma, creando e inizializzando tutti i
 * componenti che costituiscono l'interfaccia visiva del programma.
 * Contiene inoltre il main del progetto stesso.
 * @author Michela Iacopini
 */
public class Progetto extends JFrame {
   /**
    * Oggetto di tipo JPanel che identifica il pannello contenente tutti i componenti
    * grafici del gioco.
    */
    private JPanel contentPane;
    /**
     * Oggetto di tipo JPanel contenete i pannelli dei giocatori
     */
    private JPanel playerspanel;
    /**
     * Oggetto di tipo JPanel contenente il pannello centrale
     */
    private JPanel centerpanel;
    /**
     * Oggetto di tipo JPanel contenente il pannello di gioco
     */
    private JPanel gamepanel;
    /**
     * Oggetto List di tipo Player contenente la lista dei giocatori
     */
    private List<Player> players = new ArrayList<Player>();
    /**
     * Oggetto List di tipo Phrase contenente la lista delle frasi e dei suggerimenti
     */
    private List<Phrase> phrases;
    /**
     * Oggetto di tipo CenterPanel
     */
    private CenterPanel ct;
    /**
     * Oggetto di tipo GamePanel
     */
    private GamePanel gp;
    /**
     * Oggetto di tipo Menu
     */
    private Menu menu;
    /**
     * Oggetto di tipo Settings
     */
    private Settings settings;
    /**
     * Intero che identifica il numero della manche
     */
    private int game;
    /**
     * Intero che identifica il turno del giocatore 
     */
    private int  player;
    /**
     * Oggetto di tipo SaveGame per il salvataggio della partita 
     */
    private SaveGame savegame;
    /**
     * Oggetto di tipo LoadGame per il caricamento della partita
     */
    private LoadGame loadgame;
 
    /**
     *  Inizializza un nuovo oggetto Progetto il quale si occupa di inizializzare ,
     * richiamando i metodi opportuni, tutti i componenti necessari per il corretto 
     * svolgimento del gioco
     */
    public Progetto() {
        super();
        // crea un oggetto di tipo ImageIcon che recupera l'immagine che identifica
        // l'icona del programma
        ImageIcon icon = new ImageIcon(Progetto.class.getResource("image/wheel.gif"));
       // setta l'icona del progamma utilizzando l'oggetto di tipo ImageIcon
        this.setIconImage(icon.getImage());
        //inizializza l'oggetto di tipo SaveGame
        savegame = new SaveGame();
        //inizializza l'oggetto Menu
        menu = new Menu();
        // richiama il metodo InitializeMenu() per settare i vari parametri del Menu
        menu.InitializeMenu();
        // imposta l'azione della voce Nuova Partita del Menu
        menu.getNewGame().addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                newGame_actionPerformed(e);

            }
        });
        //imposta l'azione della voce Carica Partita del Menu
        menu.getLoadGame().addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                LoadGame_actionPerformed(e);

            }
        });
        // richiama il metodo initializeComponent per i vari parametri e i vari 
        //componenti
        initializeComponent();
        // setta il frame visibile
        this.setVisible(true);
    }

    /**
     * Richiama il metodo che imposta l'azione della voce Nuova Partita
     * @param e Oggetto di tipo ActionEvent con gli eventi della voce Nuova Partita
     */
    private void newGame_actionPerformed(ActionEvent e) {
        newGame();

    }
    /**
     * Richiama il metodo che imposta l'azione della voce Carica Partita
     * @param e Oggetto di tipo ActionEvent con gli eventi della voce Carica Partita
     */
    private void LoadGame_actionPerformed(ActionEvent e) {

        LoadGame();

    }
/**
 * Metodo per l'inizializazione dei componenti all'interno della classe
 */
    private void initializeComponent() {
        playerspanel = new JPanel();
        centerpanel = new JPanel();
        gamepanel = new JPanel();
        newGame();
        // inizializza un JPanel utilizzando il metodo getContentPane della classe JFrame
        contentPane = (JPanel) this.getContentPane();
        //
        // contentPane
        //
        contentPane.setLayout(null);
        addComponent(contentPane, menu.getMenuBar(), 0, 0, 930, 15);
        addComponent(contentPane, playerspanel, 0, 18, 135, 620);
        addComponent(contentPane, centerpanel, 135, 20, 600, 620);
        addComponent(contentPane, gamepanel, 620, 20, 400, 640);
        //
        // Players
        //
        playerspanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

        //
        // Progetto
        //
        this.setTitle("La ruota della Fortuna");
        // setta le coordinate del frame una volta avviato
        this.setLocation(new Point(105, 56));
        // setta la grandezza del frame
        this.setSize(new Dimension(930, 680));
        // inserisce l'azione per il pulsante di uscita del frame
        this.addWindowListener(new ExitAdapter());
        this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        this.setResizable(false);
    }
/**
 * La classe privata ExitAdapter è una classe che estende WindowAdapter e serve
 * ad impostare l'azione del pulsante di chiusura del frame, in modo tale che 
 * generi un JOptionPane per poter confermare l'uscita dal programma
 */
    private class ExitAdapter extends WindowAdapter {
        /**
         * Imposta l'azione di chiusura del JFrame
         * @param event
         */
        public void windowClosing(WindowEvent event) {
            int n = JOptionPane.showConfirmDialog(null, "Vuoi uscire dal gioco in corso?", "Esci dal gioco", JOptionPane.YES_NO_OPTION);

            if (n == 0) {
                System.exit(0);
            }
        }
    }
/**
 * Inizializza tutti i vari componenti e parametri per la creazione di una nuova partita
 */
    public void newGame() {
        ActionListener[] al = menu.getSaveGame().getActionListeners();
// rimuove tutte le azioni della voce Salva Partita per poi poterle risettarle
        for (int i = 0; i < al.length; i++) {

            menu.getSaveGame().removeActionListener(al[i]);
        }
        players.clear();
        playerspanel.removeAll();
        centerpanel.removeAll();
        gamepanel.removeAll();

        game = 0;
        savegame.setGame(game);
        settings = new Settings();
    
        phrases = settings.getPhrases();


        contentPane = (JPanel) this.getContentPane();
// inserisce la lista dei giocatori all'intero della Lista di tipo Player
        for (int i = 0; i < settings.getPlayers().size(); i++) {
            players.add(new Player(settings.getPlayers().get(i)));
        }




        //-----

        //inizializza l'oggetto CenterPanel
        ct = new CenterPanel(game, phrases, this);
        //inizializza l'oggetto GamePanel
        gp = new GamePanel();
        // richiama il metodo setProbabilities della classe GamePanel
        // per settare le probabilità lette dalla classe Settings
        gp.setProbabilities(settings.getElementsWheel());
        
        gp.setGame(game);
        ct.setPlayers(players);
        ct.setLetters(gp.getLetters());

        ct.setSaveGame(menu.getSaveGame(), savegame);
        gp.setPlayers(players);
        gp.setSaveGame(menu.getSaveGame(), savegame);



        // crea e inizializza un oggetto di tipo Random per la scelta casuale
        // del giocatore all'inizio di una partita.
        Random random = new Random();
        //  players.add(new Player("Carlo"));
        player = random.nextInt(players.size());
        players.get(player).setSelected(true);


        gp.setPlayer(player);

        gp.setLayout();
        gp.setPhrases(ct.getPhrases(), ct.getCharPhrases());


        gamepanel.add(gp);

        // Inserisce i pannelli giocatore all'interno del pannello sinistro
        for (int i = 0; i < players.size(); i++) {
            playerspanel.add(players.get(i));
        }
        // inserisce l'oggetto CenterPanel all'interno del pannello centrale
        centerpanel.add(ct);
        //
        // GamePanel
        //
        
        ct.setGamePanel(gp);
        
        // inserisce l'oggetto GamePanel all'interno del pannello sinistro
        gamepanel.add(gp);
        gamepanel.updateUI();
        centerpanel.updateUI();
        playerspanel.updateUI();
    }
/**
 * Inizializza i vari componenti e variabili per il caricamento di una partita
 */
    public void LoadGame() {
        loadgame = new LoadGame();
        loadgame.initializeLoad();
        ActionListener[] al = menu.getSaveGame().getActionListeners();

        for (int i = 0; i < al.length; i++) {

            menu.getSaveGame().removeActionListener(al[i]);
        }
        players.clear();
        playerspanel.removeAll();
        centerpanel.removeAll();
        gamepanel.removeAll();

        game = loadgame.getPhrasesNumber();
        savegame.setGame(game);
        settings = new Settings();

        phrases = settings.getPhrases();


        contentPane = (JPanel) this.getContentPane();


        players = loadgame.getPlayers();

        ct = new CenterPanel(game, phrases, this);

        gp = new GamePanel();
        gp.setProbabilities(settings.getElementsWheel());
        gp.setGame(game);
        ct.setPlayers(players);
        ct.setLetters(gp.getLetters());

        ct.setSaveGame(menu.getSaveGame(), savegame);
        gp.setPlayers(players);
        gp.setSaveGame(menu.getSaveGame(), savegame);

        gp.setPlayer(loadgame.getPlayerNumber());

        gp.setLayout();
        gp.setPhrases(ct.getPhrases(), ct.getCharPhrases());


        gamepanel.add(gp);


        players.get(loadgame.getPlayerNumber()).setSelected(true);
        for (int i = 0; i < players.size(); i++) {

            playerspanel.add(players.get(i));
        }
        ct.loadLetters(loadgame.getLetters());
        gp.loadLetters(loadgame.getLetters());
        gp.setDataWheel(loadgame.getDataString());
        gp.setWheelButton(loadgame.getWheelButton());
        gp.setPassButton(loadgame.getPassButton());
        gp.setJollyButton(loadgame.getJollyButton());
        gp.verifyLetters();

 

        centerpanel.add(ct);
   
        ct.setGamePanel(gp);
        gamepanel.add(gp);
        gamepanel.updateUI();

        centerpanel.updateUI();
        playerspanel.updateUI();
    }

    
    /**
     *  Inserisce il componente impostato da parametro all'intero del pannello generale
     *  impostando la dimensione e le coordinate
     * @param container oggetto di tipo Container per l'inserimento dei componenti grafici
     * @param c oggetto component per l'inserimento del componente grafico all'interno del container
     * @param x coordinata orrizzontale
     * @param y coordinata verticale
     * @param width larghezza del componente
     * @param height altezza del componente
     */
    private void addComponent(Container container, Component c, int x, int y, int width, int height) {
        c.setBounds(x, y, width, height);
        container.add(c);
    }

 /**
  * Main del progetto
  * @param args 
  */
    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JDialog.setDefaultLookAndFeelDecorated(true);
        try {
            // imposta il tema di java MetalLookAndFeel
            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
        } catch (Exception ex) {
          
        }
        new Progetto();
    }

}
